package com.example.g7640.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.example.g7640.dto.*;
import com.example.g7640.dto.common.PageResult;
import com.example.g7640.entity.Customer;
import com.example.g7640.entity.Vendor;
import com.example.g7640.enums.TrueFalseEnum;
import com.example.g7640.enums.UserType;
import com.example.g7640.exception.BizException;
import com.example.g7640.mapper.VendorMapper;
import com.example.g7640.service.ScoreService;
import com.example.g7640.service.UserService;
import com.example.g7640.service.VendorService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.g7640.util.*;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author
 * @since 2024-03-18
 */
@Service
public class VendorServiceImpl extends ServiceImpl<VendorMapper, Vendor> implements VendorService, UserService {

    @Resource
    VendorMapper vendorMapper;

    @Resource
    ScoreService scoreService;

    @Override
    public SessionDto login(LoginDto loginDto) {
        Vendor vendorDb = this.queryByAccount(loginDto.getAccount());
        if (vendorDb == null) {
            throw new BizException("This vendor account already exists");
        }
        String dbPassword = vendorDb.getPassword();
        if (!dbPassword.equals(loginDto.getPassword())) {
            throw new BizException("Password is wrong");
        }

        SessionDto sessionDto = new SessionDto();
        sessionDto.setId(vendorDb.getId());
        sessionDto.setAccount(vendorDb.getAccount());
        sessionDto.setName(vendorDb.getName());
        sessionDto.setType(UserType.vendor.getIndex());
        return sessionDto;
    }

    @Override
    public void register(RegistDto registDto) {
        Vendor vendorDb = this.queryByAccount(registDto.getAccount());
        if (vendorDb != null) {
            throw new BizException("This vendor account already exists");
        }
        LocalDateTime localDateTime = LocalDateTime.now();
        Vendor vendor = new Vendor();
        BeanUtils.copyProperties(registDto, vendor);
        vendor.setDeleted(TrueFalseEnum.FALSE.getCode());
        vendor.setCreatedAt(localDateTime);
        vendor.setUpdatedAt(localDateTime);
        vendorMapper.insert(vendor);
    }

    @Override
    public Integer getType() {
        return UserType.vendor.getIndex();
    }

    @Override
    public void changePassword(UserChangePasswordDto u) {
        RoleCheckUtil.checkVendor();
        Integer id = SessionLocal.getLoginId();
        Vendor vendor = vendorMapper.selectById(id);
        if(vendor == null){
            throw new BizException("vendor is not exist");
        }
        String oldPassword = PasswordUtil.encodePassword(u.getOldPass());
        String newPassword = PasswordUtil.encodePassword(u.getNewPass());
        if(!Objects.equals(oldPassword,vendor.getPassword())){
            throw new BizException("Old password wrong");
        }
        vendor.setPassword(newPassword);
        vendor.setUpdatedAt(LocalDateTime.now());
        vendorMapper.updateById(vendor);
    }


    private Vendor queryByAccount(String account) {
        LambdaQueryWrapper<Vendor> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Vendor::getAccount, account);
        wrapper.eq(Vendor::getDeleted, TrueFalseEnum.FALSE.getCode());
        List<Vendor> vendors = vendorMapper.selectList(wrapper);
        return CollectionUtil.getFirstObj(vendors);
    }


    @Override
    public PageResult<List<VendorResult>> query(VendorQuery query) {
        RoleCheckUtil.check(UserType.customer, UserType.admin);
        LambdaQueryWrapper<Vendor> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Vendor::getDeleted, TrueFalseEnum.FALSE.getCode());
        if(query.getName() != null) {
            wrapper.like(Vendor::getName, query.getName());
        }
        if(query.getLocation() != null) {
            wrapper.like(Vendor::getLocation, query.getLocation());
        }

        wrapper.orderByDesc(Vendor::getId);
        IPage iPage = vendorMapper.selectPage(PageUtil.pageToMybatisPage(query), wrapper);
        PageResult<List<VendorResult>> result = PageUtil.mybatisPageToPage(iPage, VendorResult.class);

        List<VendorResult> l = result.getData();
        for (VendorResult vendorResult : l) {
            vendorResult.setScore(scoreService.getAvg(vendorResult.getId()));
        }
        return result;
    }

    @Override
    public VendorResult getInfo(Integer id) {
        Vendor vendor = vendorMapper.selectById(id);
        VendorResult vendorResult = BaseConvertor.convert(vendor, VendorResult.class);
        vendorResult.setScore(scoreService.getAvg(vendorResult.getId()));
        return vendorResult;
    }

    @Override
    public void add(VendorDto vendorDto) {
        RoleCheckUtil.checkAdmin();
        if (vendorDto.getAccount() == null) {
            throw new BizException("no account");
        }
        if (vendorDto.getPassword() == null) {
            throw new BizException("no password");
        }
        Vendor vendor = BaseConvertor.convert(vendorDto, Vendor.class);
        vendor.setPassword(PasswordUtil.encodePassword(vendor.getPassword()));
        vendor.setUpdatedAt(LocalDateTime.now());
        vendor.setCreatedAt(LocalDateTime.now());
        vendor.setDeleted(TrueFalseEnum.FALSE.getCode());
        vendorMapper.insert(vendor);
    }

    @Override
    public void update(VendorDto vendorDto) {
        RoleCheckUtil.checkAdmin();
        Vendor convert = BaseConvertor.convert(vendorDto, Vendor.class);
        convert.setUpdatedAt(LocalDateTime.now());
        vendorMapper.updateById(convert);
    }

    @Override
    public void delete(Integer id) {
        RoleCheckUtil.checkAdmin();
        Vendor vendorDb = vendorMapper.selectById(id);
        vendorDb.setDeleted(TrueFalseEnum.TRUE.getCode());
        vendorDb.setUpdatedAt(LocalDateTime.now());
        vendorMapper.updateById(vendorDb);
    }
    @Override
    public void resetPassword(VendorDto vendorDto) {
        RoleCheckUtil.checkAdmin();
        Vendor vendorDb = vendorMapper.selectById(vendorDto.getId());
        if(vendorDb == null){
            throw new BizException("vendor is not exist");
        }
        vendorDb.setPassword(PasswordUtil.encodePassword(vendorDto.getPassword()));
        vendorDb.setUpdatedAt(LocalDateTime.now());
        vendorMapper.updateById(vendorDb);
    }
}
